package cn.lbd.zk;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class ZKCreate {
    private CountDownLatch countDownLatch = null;
    private ZooKeeper zooKeeper = null;
    private String socketAddress = "39.97.191.1:2181";

    @Before
    public void init() throws Exception {
        countDownLatch = new CountDownLatch(1);
        zooKeeper = new ZooKeeper(socketAddress, 5000, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                if (event.getState() == Event.KeeperState.SyncConnected) {
                    System.out.println("连接建立成功");
                    //连接成功，通知计数器-1
                    countDownLatch.countDown();
                }
            }
        });
        countDownLatch.await();
        System.out.println("会话ID => " + zooKeeper.getSessionId());
    }

    @Test
    public void test1() throws KeeperException, InterruptedException {
        //节点路径，节点数据（字节数组方式传递），权限列表（ACL:常量或自定义List），节点类型（临时，持久）
        zooKeeper.create("/create/demo1", "data1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println("创建节点成功");
    }

    @Test
    public void test2() throws KeeperException, InterruptedException {
        zooKeeper.create("/create/demo2", "data2".getBytes(), ZooDefs.Ids.READ_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println("创建节点成功");
    }

    @Test
    public void test3() throws KeeperException, InterruptedException {
        //自定义的权限列表
        List<ACL> acls = new ArrayList<>();
        //指定授权模式和授权对象
        //world授权模式
        Id id = new Id("world", "anyone");
        //ACL的第一个参数代表的是权限（crwda）
        acls.add(new ACL(ZooDefs.Perms.READ, id));
        acls.add(new ACL(ZooDefs.Perms.WRITE, id));
        zooKeeper.create("/create/demo3", "data3".getBytes(), acls, CreateMode.PERSISTENT);
        System.out.println("创建节点成功");
    }

    @Test
    public void test4() throws KeeperException, InterruptedException {
        //自定义的权限列表
        List<ACL> acls = new ArrayList<>();
        //指定授权模式和授权对象
        //ip授权模式
        Id id = new Id("ip", "39.97.191.1");
        //ACL的第一个参数代表的是权限（crwda）
        acls.add(new ACL(ZooDefs.Perms.ALL, id));
        zooKeeper.create("/create/demo4", "data4".getBytes(), acls, CreateMode.PERSISTENT);
        System.out.println("创建节点成功");
    }

    @Test
    public void test5() throws KeeperException, InterruptedException {
        zooKeeper.addAuthInfo("digest", "itbd:123456".getBytes());
        zooKeeper.create("/create/demo5", "data5".getBytes(), ZooDefs.Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT);
        System.out.println("创建节点成功");
    }

    @Test
    public void test6() throws KeeperException, InterruptedException {
        zooKeeper.addAuthInfo("digest", "itlin:123".getBytes());
        List<ACL> acls = new ArrayList<>();
        //auth授权模式
        Id id = new Id("auth", "itlin");
        acls.add(new ACL(ZooDefs.Perms.READ, id));
        zooKeeper.create("/create/demo6", "data6".getBytes(), acls, CreateMode.PERSISTENT);
        System.out.println("创建节点成功");
    }

    @Test
    public void test7() throws KeeperException, InterruptedException {
        List<ACL> acls = new ArrayList<>();
        //digest授权模式
        Id id = new Id("digest", "linbd:iDVWmSOxYboXNxm5ENxypD2P50U=");
        acls.add(new ACL(ZooDefs.Perms.ALL, id));
        zooKeeper.create("/create/demo7", "data7".getBytes(), acls, CreateMode.PERSISTENT);
        System.out.println("创建节点成功");
    }

    //持久化顺序节点 => 用于生成分布式唯一主键ID
    @Test
    public void test8() throws KeeperException, InterruptedException {
        String nodeName = zooKeeper.create("/create/demo8", "data8".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
        System.out.println("创建节点成功 => " + nodeName);
    }

    //临时节点
    @Test
    public void test9() throws KeeperException, InterruptedException {
        zooKeeper.create("/create/demo9", "data9".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        System.out.println("创建节点成功");
        TimeUnit.SECONDS.sleep(30);
    }

    //临时顺序节点 => 用于生成分布式锁
    @Test
    public void test10() throws KeeperException, InterruptedException {
        String nodeName = zooKeeper.create("/create/demo10", "data10".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println("创建节点成功 =>" + nodeName);
        TimeUnit.SECONDS.sleep(15);
    }

    @Test
    public void test11() throws Exception {
        zooKeeper.create("/create/demo11", "data11".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL, new AsyncCallback.StringCallback() {
            @Override
            /**
             * rc: 0代表创建节点成功
             * path:节点路径，我们指定的路径
             * ctx:上下文参数
             * name:不一定等于我们指定的节点路径名，在有序节点类型下，生成自动命名后的节点名（指定节点名 + 自增序号）
             */
            public void processResult(int rc, String path, Object ctx, String name) {
                if (rc == 0) {
                    System.out.println("创建节点成功");
                }else {
                    System.out.println("创建节点失败");
                }
                System.out.println(path);
                System.out.println(ctx);
                System.out.println(name);
            }
        },"这是一个上下文参数");
        System.out.println("开始回调");
        TimeUnit.SECONDS.sleep(10);
        System.out.println("结束");
    }

    @After
    public void destroy() throws InterruptedException {
        zooKeeper.close();
    }
}
